<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Custom TileLayer - 4.6</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.6/esri/css/main.css">

    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>

    <script src="https://js.arcgis.com/4.6/"></script>

    <script>
        require([
            "esri/Map",
            "esri/config",
            "esri/request",
            "esri/Color",
            "esri/views/SceneView",
            "esri/widgets/LayerList",
            "esri/layers/BaseTileLayer",

            "dojo/domReady!"
        ], function(
            Map, esriConfig, esriRequest, Color,
            SceneView, LayerList, BaseTileLayer
        ) {

            // *******************************************************
            // Custom tile layer class code
            // Create a subclass of BaseTileLayer
            // *******************************************************

            var TintLayer = BaseTileLayer.createSubclass({
                properties: {
                    urlTemplate: null,
                    tint: {
                        value: null,
                        type: Color
                    }
                },

                // generate the tile url for a given level, row and column
                getTileUrl: function(level, row, col) {
                    return this.urlTemplate.replace("{z}", level).replace("{x}",
                        col).replace("{y}", row);
                },

                // This method fetches tiles for the specified level and size.
                // Override this method to process the data returned from the server.
                fetchTile: function(level, row, col) {

                    // call getTileUrl() method to construct the URL to tiles
                    // for a given level, row and col provided by the LayerView
                    var url = this.getTileUrl(level, row, col);

                    // request for tiles based on the generated url
                    // set allowImageDataAccess to true to allow
                    // cross-domain access to create WebGL textures for 3D.
                    return esriRequest(url, {
                            responseType: "image",
                            allowImageDataAccess: true
                        })
                        .then(function(response) {
                            // when esri request resolves successfully
                            // get the image from the response
                            var image = response.data;
                            var width = this.tileInfo.size[0];
                            var height = this.tileInfo.size[0];

                            // create a canvas with 2D rendering context
                            var canvas = document.createElement("canvas");
                            var context = canvas.getContext("2d");
                            canvas.width = width;
                            canvas.height = height;


                            // Draw the blended image onto the canvas.
                            context.drawImage(image, 0, 0, width, height);

                            return canvas;
                        }.bind(this));
                }
            });

            // *******************************************************
            // Start of JavaScript application
            // *******************************************************

            // Add stamen url to the list of servers known to support CORS specification.
            esriConfig.request.corsEnabledServers.push("webst01.is.autonavi.com");

            // Create a new instance of the TintLayer and set its properties
            var stamenTileLayer = new TintLayer({
                urlTemplate: "http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
                tint: new Color("#004FBB"),
                title: "高德"
            });

            // add the new instance of the custom tile layer the map
            var map = new Map({
                layers: [stamenTileLayer]
            });

            // create a new scene view and add the map
            var view = new SceneView({
                container: "viewDiv",
                map: map,
                center: [0, 30],
                zoom: 3
            });

            // create a layer list widget
            var layerList = new LayerList({
                view: view,
            });
            view.ui.add(layerList, "top-right");
        });
    </script>
</head>

<body>
    <div id="viewDiv"></div>
</body>

</html>